﻿using System;
using System.IO;
using System.Xml;

namespace Fineout.ConfigShellSettings.Xml
{
    public static class XmlHelper
    {
        public static XmlDocument LoadDocument(string path)
        {
            try
            {
                var doc = new XmlDocument();
                doc.Load(path);
                return doc;
            }
            catch (FileNotFoundException e)
            {
                throw new XmlHelperException("XML file not found.", e);
            }
            catch (Exception e)
            {
                throw new XmlHelperException("Error reading XML file.", e);
            }
        }

        /// <summary>
        /// Used to load up the default namespace reference and prefix information.
        /// This is required so that SelectSingleNode can find info in 2.0 or later
        /// config files that include a namespace on the root element definition.
        /// See also: http://www.west-wind.com/Weblog/posts/2423.aspx
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="namespacePrefix"></param>
        /// <param name="namespaceManager"></param>
        // ReSharper disable RedundantAssignment
        public static void GetNameSpaceInfo(
            XmlDocument doc,
            ref string namespacePrefix,
            ref XmlNamespaceManager namespaceManager)
        // ReSharper restore RedundantAssignment
        {
            // *** Load up the Namespaces object so we can
            // *** reference the appropriate default namespace
            if (doc.DocumentElement == null || doc.DocumentElement.NamespaceURI == "")
            {
                namespaceManager = null;
                namespacePrefix = "";
            }
            else
            {
                namespacePrefix = String.IsNullOrEmpty(doc.DocumentElement.Prefix)
                                         ? "ww"
                                         : doc.DocumentElement.Prefix;

                namespaceManager = new XmlNamespaceManager(doc.NameTable);
                namespaceManager.AddNamespace(namespacePrefix,
                                           doc.DocumentElement.NamespaceURI);

                namespacePrefix += ":";
            }
        }

        public static XmlAttribute CreateAttribute(
            XmlDocument doc,
            string attributeName,
            string attributeValue)
        {
            var attribute = doc.CreateAttribute(attributeName);
            attribute.Value = attributeValue;

            return attribute;
        }

        public static void UpdateAttribute(
            XmlDocument doc,
            XmlNode node,
            string attributeName,
            string newAttributeValue,
            ref bool change)
        {
            if (node.Attributes == null)
                return;

            var attribute = node.Attributes[attributeName];
            if (attribute == null)
            {
                node.Attributes.Append(CreateAttribute(doc, attributeName, newAttributeValue));
                change = true;
            }
            else if (attribute.Value != newAttributeValue)
            {
                attribute.Value = newAttributeValue;
                change = true;
            }
        }
    }

    #region Exceptions

    public class XmlHelperException : Exception
    {
        public XmlHelperException()
        { }

        public XmlHelperException(string message)
            : base(message)
        { }

        public XmlHelperException(string message, Exception innerException)
            : base(message, innerException)
        { }
    }

    #endregion Exceptions
}
